package redecolaborativa.testes;

import java.util.GregorianCalendar;
import java.util.LinkedList;

//import redecolaborativa.enums.Categoria;
import redecolaborativa.excecoes.*;
import redecolaborativa.objetos.Item;
import redecolaborativa.sistema.*;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;

public class TesteItem {
	private Usuario dono;
	private Item item, item2;
	private LinkedList<String> categorias = new LinkedList<String>();
	
	@Before
	public void iniciaTeste() throws Exception {
		Item.resetaGeradorID();
		dono = new Usuario("Isabelly", "isabellylr", "Bodocongo");
		categorias.add("Filme"); categorias.add("Livro");
		item = new Item("Senhor dos Aneis", categorias, "Livro de Ficcao", dono);
		item2 = new Item("Harry Potter", categorias, "J.K", dono);
	}
	
	@Test
	public void testaConstrutor() throws Exception {
		try {
			item = new Item(" ", categorias, "Livro de Ficcao", dono);
			fail("Esperava excecao de nome invalido.");
		} catch(NomeInvalidoException ex){
			assertEquals("Mensagem errada", "Nome inválido", ex.getMessage());
		}
		try {
			item = new Item(null, categorias, "Livro de Ficcao", dono);
			fail("Esperava excecao de nome invalido.");
		} catch(NomeInvalidoException ex) {
			assertEquals("Mensagem errada", "Nome inválido", ex.getMessage());
		}
		try {
			item = new Item("Senhor dos aneis", null, "Livro de Ficcao", dono);
			fail("Esperava excecao de categoria invalido.");
		} catch(CategoriaInvalidaException ex){
			assertEquals("Mensagem errada", "Categoria inválida.", ex.getMessage());
		}
		try {
			item = new Item("Senhor dos Aneis ", categorias, " ", dono);
			fail("Esperava excecao de item invalido.");
		} catch(DescricaoInvalidaException ex) {
			assertEquals("Mensagem errada", "Descricao nao pode ser nulo ou vazio.", ex.getMessage());
		}
		try {
			item = new Item("Senhor dos aneis", categorias, null, dono);
			fail("Esperava excecao de item invalido.");
		} catch(DescricaoInvalidaException ex) {
			assertEquals("Mensagem errada", "Descricao nao pode ser nulo ou vazio.", ex.getMessage());
		}
		try {
			item = new Item("Senhor dos aneis", categorias, "Descricao", null);
			fail("Esperava excecao de dono invalido.");
		} catch(DonoInvalidoException ex) {
			assertEquals("Mensagem errada", "Dono nao pode ser nulo.", ex.getMessage());
		}
	}
	
	@Test 
	public void testaGetDeItem() throws Exception {
		assertEquals("Nome errado", "Senhor dos Aneis", item.getNome());
		assertEquals("Categoria errada", categorias , item.getCategoria());
		assertEquals("Descricao errada", "Livro de Ficcao", item.getDescricao());
		assertEquals("Dono errado", dono, item.getDono());
		assertEquals("ID errado", 1, item.getID());
		assertEquals("ID errado", 2, item2.getID());
		assertEquals("Data de criacao errada", (new GregorianCalendar()).getGregorianChange(), item.getDataDeCriacao().getGregorianChange());
		assertTrue(item.estaDisponivel());
		assertFalse(item.foiDevolvido());
	}
	
	@Test
	public void testaSetDisponibilidade() throws Exception {
		Usuario usuario = new Usuario("Isabelly Rocha", "isabelly", "Bodocongo");
		usuario.requisitarAmizade(dono);
		dono.aprovarAmizade(usuario);
		
		assertTrue(item.estaDisponivel());
		item.setDisponibilidade(false);
		usuario.registraInteresseEmItem(item);
		item.setDisponibilidade(true);
		assertTrue(usuario.gerenteDeItens().getNotificacoesDeItemLivre().contains(item));
	}
	
	@Test
	public void testaGetAtributo() throws Exception {
		try {
			item.getAtributo(null);
			fail("Esperava excecao de atributo inválido");
		} catch (AtributoInvalidoException ex) {
			assertEquals("Atributo inválido", ex.getMessage());
		}
		try {
			item.getAtributo("");
			fail("Esperava excecao de atributo inválido");
		} catch (AtributoInvalidoException ex) {
			assertEquals("Atributo inválido", ex.getMessage());
		}
		try {
			item.getAtributo("blabla");
			fail("Esperava excecao de atributo inválido");
		} catch (AtributoInvalidoException ex) {
			assertEquals("Atributo inexistente", ex.getMessage());
		}
		assertEquals(item.getAtributo("nome"), "Senhor dos Aneis");
		assertEquals(item.getAtributo("descricao"), "Livro de Ficcao");
		assertEquals(item.getAtributo("categoria"), "Filme,Livro");
	}

	@Test
	public void testaSetDevolucao() {
		assertFalse(item.foiDevolvido());
		item.setDevolucao(true);
		assertTrue(item.foiDevolvido());
	}
	
	@Test
	public void testaAdicionaRemoveInteressado() throws Exception {
		Usuario interessado = new Usuario("Interessado", "interessado", "blabla");
		item.adicionaInteressado(interessado);
		assertEquals(1, item.getInteressados().size());
		try {
			item.adicionaInteressado(interessado);
			fail("Esperava excecao de usuario já registou interesse no item.");
		} catch (PermissaoNegadaException ex) {
			assertEquals("O usuário já registrou interesse neste item", ex.getMessage());
		}
		
		item.removeInteressado(interessado);
		assertEquals(0, item.getInteressados().size());
	}
	
	@Test
	public void testaEquals() throws Exception {
		Item outroItem = new Item("Senhor dos Aneis", categorias, "Filme de Ficcao", dono);
		Item itemIgual = new Item("Senhor dos Aneis", categorias, "Livro de Ficcao", dono);
		assertTrue(item.equals(item));
		assertFalse(item.equals(outroItem));
		assertTrue(item.equals(itemIgual));
		assertTrue(itemIgual.equals(item));
	}
}